﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using DevExpress.Xpo;
using DevExpress.Xpo.DB;

namespace LprMiddleWare
{
    public static class Helper
    {
        private static NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();
        public static IDataLayer ConnectToOracleDb(string server, string user, string password)
        {

            var conn = MSSqlConnectionProvider.GetConnectionString(server, user, password, "TransLogger");
            var dataLayer = XpoDefault.GetDataLayer(conn, AutoCreateOption.SchemaAlreadyExists);
            return dataLayer;
        }

        public static IDataLayer ConnectToDbUntilSuccess(string server, string user, string password)
        {
            while (true)
            {
                try
                {
                    var dataLayer = ConnectToOracleDb(server, user, password);
                    return dataLayer;
                }
                catch (Exception ex)
                {
                    Thread.Sleep(10000);
                }

            }
        }

        public static string[] ReadWhiteList(string fileName)
        {
            var buffer = new byte[0];
            var decryptedData = new byte[0];
            if (File.Exists(fileName))
            {
                buffer = File.ReadAllBytes(fileName);
                decryptedData = ProtectedData.Unprotect(buffer, null, DataProtectionScope.LocalMachine);
            }


            return ReadAllLines(new MemoryStream(decryptedData), Encoding.Unicode);


        }

        public static void WriteWhiteList(string fileName, string[] names)
        {
            var lines = string.Join(Environment.NewLine, names);
            var data = Encoding.Unicode.GetBytes(lines);
            var protectedData = ProtectedData.Protect(data, null, DataProtectionScope.LocalMachine);
            File.WriteAllBytes(fileName, new byte[0]);
            File.WriteAllBytes(fileName, protectedData);
        }

        public static string[] ReadAllLines(Stream stream, Encoding encoding)
        {
            using (var reader =
               new StreamReader(stream, encoding))
            {
                var lines = new List<string>();
                while (true)
                {
                    var line = reader.ReadLine();
                    if (line == null)
                    {
                        break;
                    }

                    lines.Add(line);
                }

                return lines.ToArray();
            }
        }


        public static void Save(this Image image, Stream stream, int quality)
        {
            // Get a bitmap.
            ImageCodecInfo jgpEncoder = GetEncoder(ImageFormat.Jpeg);

            // Create an Encoder object based on the GUID 
            // for the Quality parameter category.
            System.Drawing.Imaging.Encoder myEncoder =
                System.Drawing.Imaging.Encoder.Quality;

            // Create an EncoderParameters object. 
            // An EncoderParameters object has an array of EncoderParameter 
            // objects. In this case, there is only one 
            // EncoderParameter object in the array.
            EncoderParameters myEncoderParameters = new EncoderParameters(1);

            EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, quality);
            myEncoderParameters.Param[0] = myEncoderParameter;
            image.Save(stream, jgpEncoder, myEncoderParameters);
        }




        private static ImageCodecInfo GetEncoder(ImageFormat format)
        {

            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();

            foreach (ImageCodecInfo codec in codecs)
            {
                if (codec.FormatID == format.Guid)
                {
                    return codec;
                }
            }
            return null;
        }


        public static byte[] CompressImage(byte[] imageBuffer, int maxImageFileSize)
        {
            var quality = 75;
            while (true)
            {
                var buffer = CompressImageToBinary(imageBuffer, quality);
                if (buffer.Length <= maxImageFileSize)
                {
                    return buffer;
                }
                quality -= 10;
            }

        }

        private static byte[] CompressImageToBinary(byte[] imageBuffer, int quality)
        {
            using (var inputStream = new MemoryStream(imageBuffer))
            using (var outputStream = new MemoryStream())
            using (var img = Image.FromStream(inputStream))
            {
                img.Save(outputStream, quality);
                return outputStream.ToArray();
            }
        }


        [DllImport("kernel32.dll")]
        public extern static uint SetSystemTime(ref SystemTime lpSystemTime);

        [DllImport("kernel32.dll")]
        public extern static void GetSystemTime(ref SystemTime lpSystemTime);
    }
}
